home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 44 / PC Actual CD 44.iso / Linux / Cygwin / full.exe / Disk1 / data1.cab / Tools / share / tix4.1 / PanedWin.tcl < prev    next >
Encoding:
Text File  |  1998-12-04  |  27.6 KB  |  1,216 lines

  1. # PanedWin.tcl --
  2. #
  3. #    This file implements the TixPanedWindow widget
  4. #
  5. # Copyright (c) 1996, Expert Interface Technologies
  6. #
  7. # See the file "license.terms" for information on usage and redistribution
  8. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  9. #
  10.  
  11.  
  12. tixWidgetClass tixPanedWindow {
  13.     -classname TixPanedWindow
  14.     -superclass tixPrimitive
  15.     -method {
  16.     add delete forget manage panecget paneconfigure panes setsize
  17.     }
  18.     -flag {
  19.     -command -dynamicgeometry -handleactivebg -handlebg -orient
  20.     -orientation -panebd -paneborderwidth -panerelief
  21.     -separatoractivebg -separatorbg
  22.     }
  23.     -static {
  24.     -orientation
  25.     }
  26.     -configspec {
  27.     {-command command Command ""}
  28.     {-dynamicgeometry dynamicGeometry DynamicGeometry 1 tixVerifyBoolean}
  29.     {-handleactivebg handleActiveBg HandleActiveBg #ececec}
  30.     {-handlebg handleBg Background #d9d9d9}
  31.     {-orientation orientation Orientation vertical}
  32.     {-paneborderwidth paneBorderWidth PaneBorderWidth 1}
  33.     {-panerelief paneRelief PaneRelief raised}
  34.     {-separatoractivebg separatorActiveBg SeparatorActiveBg red}
  35.     {-separatorbg separatorBg Background #d9d9d9}
  36.     }
  37.     -alias {
  38.     {-panebd -paneborderwidth}
  39.     {-orient -orientation}
  40.     }
  41. }
  42.  
  43. #----------------------------------------------------------------------
  44. # ClassInitialization:
  45. #----------------------------------------------------------------------
  46.  
  47. proc tixPanedWindow:InitWidgetRec {w} {
  48.     upvar #0 $w data
  49.  
  50.     tixChainMethod $w InitWidgetRec
  51.  
  52.     set data(items)       ""
  53.     set data(nItems)      0
  54.     set data(totalsize)   0
  55.     set data(movePending) 0
  56.  
  57.     set data(repack)      0
  58.     set data(counter)     0
  59.  
  60.     set data(maxReqW)     1
  61.     set data(maxReqH)     1
  62. }
  63.  
  64. proc tixPanedWindow:ConstructWidget {w} {
  65.     upvar #0 $w data
  66.  
  67.     tixChainMethod $w ConstructWidget
  68.     # Do nothing
  69. }
  70.  
  71. proc tixPanedWindow:SetBindings {w} {
  72.     upvar #0 $w data
  73.  
  74.     tixChainMethod $w SetBindings
  75.  
  76.     bind $w <Configure> [list tixPanedWindow:MasterGeomProc $w ""]
  77. }
  78.  
  79. #----------------------------------------------------------------------
  80. # ConfigOptions:
  81. #----------------------------------------------------------------------
  82. proc tixPanedWindow:config-handlebg {w arg} {
  83.     upvar #0 $w data
  84.  
  85.     for {set i 1} {$i < $data(nItems)} {incr i} {
  86.     $data(btn,$i) config -bg $arg
  87.     }
  88. }
  89.  
  90. #----------------------------------------------------------------------
  91. # PublicMethods:
  92. #----------------------------------------------------------------------
  93.  
  94.  
  95. # method: add
  96. #
  97. #    Adds a new pane into the PanedWindow.
  98. #
  99. # options -size -max -min -allowresize
  100. #
  101. proc tixPanedWindow:add {w name args} {
  102.     upvar #0 $w data
  103.  
  104.     if {[winfo exists $w.$name] && !$data($name,forgotten)} {
  105.     error "Pane $name is already managed"
  106.     }
  107.     # Step 1: Parse the options to get the children's size options
  108.  
  109.     # The default values
  110.     #
  111.     if [info exists data($name,forgotten)] {
  112.     set option(-size)        $data($name,size)
  113.     set option(-min)         $data($name,min)
  114.     set option(-max)         $data($name,max)
  115.     set option(-allowresize) $data($name,allowresize)
  116.     set option(-expand)      $data($name,expand)
  117.     } else {
  118.     set option(-size)        0
  119.     set option(-min)         0
  120.     set option(-max)         100000
  121.     set option(-allowresize) 1
  122.     set option(-expand)      0
  123.     }
  124.  
  125.     set option(-before)      ""
  126.     set option(-after)       ""
  127.     set option(-at)          ""
  128.     set validOpts {-after -allowresize -at -before -expand -max -min -size}
  129.  
  130.     tixHandleOptions option $validOpts $args
  131.  
  132.     set data($name,size)        $option(-size)
  133.     set data($name,rsize)       $option(-size)
  134.     set data($name,min)         $option(-min)
  135.     set data($name,max)         $option(-max)
  136.     set data($name,allowresize) $option(-allowresize)
  137.     set data($name,expand)      $option(-expand)
  138.     set data($name,forgotten)   0
  139.  
  140.     if {$data($name,expand) < 0} {
  141.     set data($name,expand) 0
  142.     }
  143.  
  144.     # Step 2: Add the frame and the separator (if necessary)
  145.     #
  146.     if {![winfo exist $w.$name]} {
  147.     # need to check because the frame may have been "forget'ten"
  148.     #
  149.     frame $w.$name -bd $data(-paneborderwidth) -relief $data(-panerelief)
  150.     }
  151.  
  152.     if {$option(-at) != ""} {
  153.     set at [tixGetInt $option(-at)]
  154.     if {$at < 0} {
  155.         set at 0
  156.     }
  157.     } elseif {$option(-after) != ""} {
  158.     set index [lsearch -exact $data(items) $option(-after)]
  159.     if {$index == -1} {
  160.         error "Pane $option(-after) doesn't exists"
  161.     } else {
  162.         set at [incr index]
  163.     }
  164.     } elseif {$option(-before) != ""} {
  165.     set index [lsearch -exact $data(items) $option(-before)]
  166.     if {$index == -1} {
  167.         error "Pane $option(-before) doesn't exists"
  168.     }
  169.     set at $index
  170.     } else {
  171.     set at end
  172.     }
  173.  
  174.     set data(items) [linsert $data(items) $at $name]    
  175.     incr data(nItems)
  176.  
  177.     if {$data(nItems) > 1} {
  178.     tixPanedWindow:AddSeparator $w
  179.     }
  180.     set data(w:$name) $w.$name
  181.  
  182.     # Step 3: Add the new frame. Adjust the window later (do when idle)
  183.     #
  184.     tixManageGeometry $w.$name "tixPanedWindow:ClientGeomProc $w"
  185.     bind $w.$name <Configure> \
  186.     [list tixPanedWindow:ClientGeomProc $w "" $w.$name]
  187.  
  188.     tixPanedWindow:RepackWhenIdle $w
  189.  
  190.     return $w.$name
  191. }
  192.  
  193. proc tixPanedWindow:manage {w name args} {
  194.     upvar #0 $w data
  195.  
  196.     if {![winfo exists $w.$name]} {
  197.     error "Pane $name does not exist"
  198.     }
  199.     if {!$data($name,forgotten)} {
  200.     error "Pane $name is already managed"
  201.     }
  202.     tixMapWindow $data(w:$name)
  203.     eval tixPanedWindow:add $w [list $name] $args
  204. }
  205.  
  206. proc tixPanedWindow:forget {w name} {
  207.     upvar #0 $w data
  208.  
  209.     if {![winfo exists $w.$name]} {
  210.     error "Pane $name does not exist"
  211.     }
  212.     if $data($name,forgotten) {
  213.     # It has already been forgotten
  214.     #
  215.     return
  216.     }
  217.  
  218.     set items ""
  219.     foreach item $data(items) {
  220.     if {$item != $name} {
  221.         lappend items $item
  222.     }
  223.     }
  224.     set data(items) $items
  225.     incr data(nItems) -1
  226.  
  227.     set i $data(nItems)
  228.     if {$i > 0} {
  229.     destroy $data(btn,$i)
  230.     destroy $data(sep,$i)
  231.     unset data(btn,$i)
  232.     unset data(sep,$i)
  233.     }
  234.     set data($name,forgotten) 1
  235.  
  236.     tixUnmapWindow $w.$name
  237.  
  238.     tixPanedWindow:RepackWhenIdle $w
  239. }
  240.  
  241. proc tixPanedWindow:delete {w name} {
  242.     upvar #0 $w data
  243.  
  244.     if {![winfo exists $w.$name]} {
  245.     error "Pane $name does not exist"
  246.     }
  247.  
  248.  
  249.     if {!$data($name,forgotten)} {
  250.     set items ""
  251.     foreach item $data(items) {
  252.         if {$item != $name} {
  253.         lappend items $item
  254.         }
  255.     }
  256.     set data(items) $items
  257.     incr data(nItems) -1
  258.  
  259.     set i $data(nItems)
  260.     if {$i > 0} {
  261.         destroy $data(btn,$i)
  262.         destroy $data(sep,$i)
  263.         unset data(btn,$i)
  264.         unset data(sep,$i)
  265.     }
  266.     }
  267.     unset data($name,allowresize)
  268.     unset data($name,expand)
  269.     unset data($name,forgotten)
  270.     unset data($name,max)
  271.     unset data($name,min)
  272.     unset data($name,rsize)
  273.     unset data($name,size)
  274.     unset data(w:$name)
  275.     destroy $w.$name
  276.  
  277.     tixPanedWindow:RepackWhenIdle $w
  278. }
  279.  
  280. proc tixPanedWindow:paneconfigure {w name args} {
  281.     upvar #0 $w data
  282.  
  283.     if {![info exists data($name,size)]} {
  284.     error "pane \"$name\" does not exist in $w"
  285.     }
  286.  
  287.     set len [llength $args]
  288.  
  289.     if {$len == 0} {
  290.     set value [$data(w:$name) configure]
  291.     lappend value [list -allowresize "" "" "" $data($name,allowresize)]
  292.     lappend value [list -expand "" "" "" $data($name,expand)]
  293.     lappend value [list -max "" "" "" $data($name,max)]
  294.     lappend value [list -min "" "" "" $data($name,min)]
  295.     lappend value [list -size "" "" "" $data($name,size)]
  296.     return $value
  297.     }
  298.  
  299.     if {$len == 1} {
  300.     case [lindex $args 0] {
  301.         -allowresize {
  302.         return [list -allowresize "" "" "" $data($name,allowresize)]
  303.         }
  304.         -expand {
  305.         return [list -expand "" "" "" $data($name,expand)]
  306.         }
  307.         -min {
  308.         return [list -min "" "" "" $data($name,min)]
  309.         }
  310.         -max {
  311.         return [list -max "" "" "" $data($name,max)]
  312.         }
  313.         -size {
  314.         return [list -size "" "" "" $data($name,size)]
  315.         }
  316.         default {
  317.         return [$data(w:$name) configure [lindex $args 0]]
  318.         }
  319.     }
  320.     }
  321.  
  322.     # By default handle each of the options
  323.     #
  324.     set option(-allowresize) $data($name,allowresize)
  325.     set option(-expand)      $data($name,expand)
  326.     set option(-min)         $data($name,min)
  327.     set option(-max)         $data($name,max)
  328.     set option(-size)        $data($name,size)
  329.  
  330.     tixHandleOptions -nounknown option {-allowresize -expand -max -min -size} \
  331.     $args
  332.  
  333.     #
  334.     # the widget options
  335.     set new_args ""
  336.     tixForEach {flag value} $args {
  337.     case $flag {
  338.         {-expand -min -max -allowresize -size} {
  339.  
  340.         }
  341.         default {
  342.         lappend new_args $flag
  343.         lappend new_args $value
  344.         }
  345.     }
  346.     }
  347.  
  348.     if {[llength $new_args] >= 2} {
  349.     eval $data(w:$name) configure $new_args
  350.     }
  351.  
  352.     #
  353.     # The add-on options
  354.     set data($name,allowresize) $option(-allowresize)
  355.     set data($name,expand)      $option(-expand)
  356.     set data($name,max)         $option(-max)
  357.     set data($name,min)         $option(-min)
  358.     set data($name,rsize)       $option(-size)
  359.     set data($name,size)        $option(-size)
  360.  
  361.     # 
  362.     # Integrity check
  363.     if {$data($name,expand) < 0} {
  364.     set data($name,expand) 0
  365.     }
  366.     if {$data($name,size) < $data($name,min)} {
  367.     set data($name,size) $data($name,min)
  368.     }
  369.     if {$data($name,size) > $data($name,max)} {
  370.     set data($name,size) $data($name,max)
  371.     }
  372.  
  373.     tixPanedWindow:RepackWhenIdle $w
  374.     return ""
  375. }
  376.  
  377. proc tixPanedWindow:panecget {w name option} {
  378.     upvar #0 $w data
  379.  
  380.     if {![info exists data($name,size)]} {
  381.     error "pane \"$name\" does not exist in $w"
  382.     }
  383.  
  384.     case $option {
  385.     {-min -max -allowresize -size} {
  386.         regsub \\\- $option "" option
  387.         return "$data($name,$option)"
  388.     }
  389.     default {
  390.         return [$data(w:$name) cget $option]
  391.     }
  392.     }
  393. }
  394.  
  395. # return the name of all panes
  396. proc tixPanedWindow:panes {w} {
  397.     upvar #0 $w data
  398.  
  399.     return $data(items)
  400. }
  401.  
  402. # set the size of a pane, specifying which direction it should
  403. # grow/shrink
  404. proc tixPanedWindow:setsize {w item size {direction next}} {
  405.     upvar #0 $w data
  406.  
  407.     set posn [lsearch $data(items) $item]
  408.     if {$posn == -1} {
  409.     error "pane \"$item\" does not exist"
  410.     }
  411.  
  412.     set diff [expr $size - $data($item,size)]
  413.     if {$diff == 0} {
  414.     return
  415.     }
  416.  
  417.     if {$posn == 0 && $direction == "prev"} {
  418.     set direction next
  419.     }
  420.     if {$posn == [expr $data(nItems)-1] && $direction == "next"} {
  421.     set direction prev
  422.     }
  423.  
  424.     if {$data(-orientation) == "vertical"} {
  425.         set rx [winfo rooty $data(w:$item)]
  426.     } else {
  427.         set rx [winfo rootx $data(w:$item)]
  428.     }
  429.     if {$direction == "prev"} {
  430.     set rx [expr $rx - $diff]
  431.     } elseif {$data(-orientation) == "vertical"} {
  432.     set rx [expr $rx + [winfo height $data(w:$item)] + $diff]
  433.     incr posn
  434.     } else {
  435.     set rx [expr $rx + [winfo width $data(w:$item)] + $diff]
  436.     incr posn
  437.     }
  438.  
  439.     # Set up the panedwin in a proper state
  440.     #
  441.     tixPanedWindow:BtnDown $w $posn 1
  442.     tixPanedWindow:BtnMove $w $posn $rx 1
  443.     tixPanedWindow:BtnUp $w $posn 1
  444.  
  445.     return $data(items)
  446. }
  447.  
  448. #----------------------------------------------------------------------
  449. # PrivateMethods:
  450. #----------------------------------------------------------------------
  451.  
  452. proc tixPanedWindow:AddSeparator {w} {
  453.     global tcl_platform
  454.  
  455.     upvar #0 $w data
  456.  
  457.     set n [expr $data(nItems)-1]
  458.  
  459.     # CYGNUS LOCAL: On Windows, use relief ridge and a thicker line.
  460.     if {$tcl_platform(platform) == "windows"} then {
  461.       set relief "ridge"
  462.       set thickness 4
  463.     } else {
  464.       set relief "sunken"
  465.       set thickness 2
  466.     }
  467.     if {$data(-orientation) == "vertical"} {
  468.     set data(sep,$n) [frame $w.sep$n -relief $relief \
  469.         -bd 1 -height $thickness -width 10000 -bg $data(-separatorbg)]
  470.     } else {
  471.     set data(sep,$n) [frame $w.sep$n -relief $relief \
  472.         -bd 1 -width $thickness -height 10000 -bg $data(-separatorbg)]
  473.     }
  474.  
  475.     set data(btn,$n) [frame $w.btn$n -relief raised \
  476.     -bd 1 -width 9 -height 9 \
  477.     -bg $data(-handlebg)]
  478.  
  479.     if {$data(-orientation) == "vertical"} {
  480.     set cursor sb_v_double_arrow
  481.     } else {
  482.     set cursor sb_h_double_arrow
  483.     }
  484.     $data(sep,$n) config -cursor $cursor
  485.     $data(btn,$n) config -cursor $cursor
  486.  
  487.     foreach wid "$data(btn,$n) $data(sep,$n)" {
  488.     bind $wid \
  489.         <ButtonPress-1>   "tixPanedWindow:BtnDown $w $n"
  490.     bind $wid \
  491.         <ButtonRelease-1> "tixPanedWindow:BtnUp   $w $n"
  492.     bind $wid \
  493.         <Any-Enter>       "tixPanedWindow:HighlightBtn $w $n"
  494.     bind $wid \
  495.         <Any-Leave>       "tixPanedWindow:DeHighlightBtn $w $n"
  496.     }
  497.  
  498.     if {$data(-orientation) == "vertical"} {
  499.     bind  $data(btn,$n) <B1-Motion> \
  500.         "tixPanedWindow:BtnMove $w $n %Y"
  501.     } else {
  502.     bind  $data(btn,$n) <B1-Motion> \
  503.         "tixPanedWindow:BtnMove $w $n %X"
  504.     }
  505.  
  506.     if {$data(-orientation) == "vertical"} {
  507. #    place $data(btn,$n) -relx 0.90 -y [expr "$data(totalsize)-5"]
  508. #    place $data(sep,$n) -x 0 -y [expr "$data(totalsize)-1"] -relwidth 1
  509.     } else {
  510. #    place $data(btn,$n) -rely 0.90 -x [expr "$data(totalsize)-5"]
  511. #    place $data(sep,$n) -y 0 -x [expr "$data(totalsize)-1"] -relheight 1
  512.     }
  513. }
  514.  
  515. proc tixPanedWindow:BtnDown {w item {fake 0}} {
  516.     upvar #0 $w data
  517.  
  518.     if {$data(-orientation) == "vertical"} {
  519.     set spec -height
  520.     } else {
  521.     set spec -width
  522.     }
  523.  
  524.     if {!$fake} {
  525.     for {set i 1} {$i < $data(nItems)} {incr i} {
  526.         $data(sep,$i) config -bg $data(-separatoractivebg) $spec 1
  527.     }
  528.     update idletasks
  529.     $data(btn,$item) config -relief sunken
  530.     }
  531.  
  532.     tixPanedWindow:GetMotionLimit $w $item $fake
  533.  
  534.     if {!$fake} {
  535.     grab -global $data(btn,$item)
  536.     }
  537.     set data(movePending) 0
  538. }
  539.  
  540. proc tixPanedWindow:Min2 {a b} {
  541.     if {$a < $b} {
  542.     return $a
  543.     } else {
  544.     return $b
  545.     }
  546. }
  547.  
  548. proc tixPanedWindow:GetMotionLimit {w item fake} {
  549.     upvar #0 $w data
  550.  
  551.     set curBefore 0
  552.     set minBefore 0
  553.     set maxBefore 0
  554.  
  555.     for {set i 0} {$i < $item} {incr i} {
  556.     set name [lindex $data(items) $i]
  557.     incr curBefore $data($name,size)
  558.     incr minBefore $data($name,min)
  559.     incr maxBefore $data($name,max)
  560.     }
  561.  
  562.     set curAfter 0
  563.     set minAfter 0
  564.     set maxAfter 0
  565.     while {$i < $data(nItems)} {
  566.     set name [lindex $data(items) $i]
  567.     incr curAfter $data($name,size)
  568.     incr minAfter $data($name,min)
  569.     incr maxAfter $data($name,max)
  570.     incr i
  571.     }
  572.  
  573.     set beforeToGo [tixPanedWindow:Min2 \
  574.         [expr "$curBefore-$minBefore"] [expr "$maxAfter-$curAfter"]]
  575.  
  576.     set afterToGo [tixPanedWindow:Min2 \
  577.         [expr "$curAfter-$minAfter"] [expr "$maxBefore-$curBefore"]]
  578.  
  579.     set data(beforeLimit) [expr "$curBefore-$beforeToGo"]
  580.     set data(afterLimit)  [expr "$curBefore+$afterToGo"]
  581.     set data(curSize)     $curBefore
  582.  
  583.     if {!$fake} {
  584.     tixPanedWindow:PlotHandles $w 1
  585.     }
  586. }
  587.  
  588. # Compress the motion so that update is quick even on slow machines
  589. #
  590. # rootp = root position (either rootx or rooty)
  591. proc tixPanedWindow:BtnMove {w item rootp {fake 0}} {
  592.     upvar #0 $w data
  593.  
  594.     set data(rootp) $rootp
  595.  
  596.     if {$fake} {
  597.     tixPanedWindow:BtnMoveCompressed $w $item $fake
  598.     } else {
  599.     if {$data(movePending) == 0} {
  600.         after 2 tixPanedWindow:BtnMoveCompressed $w $item
  601.         set data(movePending) 1
  602.     }
  603.     } 
  604. }
  605.  
  606. proc tixPanedWindow:BtnMoveCompressed {w item {fake 0}} {
  607.     if {![winfo exists $w]} {
  608.     return
  609.     }
  610.  
  611.     upvar #0 $w data
  612.  
  613.     if {$data(-orientation) == "vertical"} {
  614.     set p [expr $data(rootp)-[winfo rooty $w]]
  615.     } else {
  616.     set p [expr $data(rootp)-[winfo rootx $w]]
  617.     }
  618.  
  619.     if {$p == $data(curSize)} {
  620.     set data(movePending) 0
  621.     return
  622.     }
  623.  
  624.     if {$p < $data(beforeLimit)} {
  625.     set p $data(beforeLimit)
  626.     }
  627.     if {$p >= $data(afterLimit)} {
  628.     set p $data(afterLimit)
  629.     }
  630.     tixPanedWindow:CalculateChange $w $item $p $fake
  631.  
  632.     if {!$fake} {
  633.     # Force the redraw to happen
  634.     #
  635.     update idletasks
  636.     }
  637.     set data(movePending) 0
  638. }
  639.  
  640. # Calculate the change in response to mouse motions
  641. #
  642. proc tixPanedWindow:CalculateChange {w item p {fake 0}} {
  643.     upvar #0 $w data
  644.  
  645.     if {$p < $data(curSize)} {
  646.     tixPanedWindow:MoveBefore $w $item $p
  647.     } elseif {$p > $data(curSize)} {
  648.     tixPanedWindow:MoveAfter $w $item $p
  649.     }
  650.  
  651.     if {!$fake} {
  652.     tixPanedWindow:PlotHandles $w 1
  653.     }
  654. }
  655.  
  656. proc tixPanedWindow:MoveBefore {w item p} {
  657.     upvar #0 $w data
  658.  
  659.     set n [expr "$data(curSize)-$p"]
  660.  
  661.     # Shrink the frames before
  662.     #
  663.     set from [expr $item-1]
  664.     set to   0
  665.     tixPanedWindow:Iterate $w $from $to tixPanedWindow:Shrink $n
  666.  
  667.     # Adjust the frames after
  668.     #
  669.     set from $item
  670.     set to   [expr "$data(nItems)-1"]
  671.     tixPanedWindow:Iterate $w $from $to tixPanedWindow:Grow $n
  672.  
  673.     set data(curSize) $p
  674. }
  675.  
  676. proc tixPanedWindow:MoveAfter {w item p} {
  677.     upvar #0 $w data
  678.  
  679.     set n    [expr "$p-$data(curSize)"]
  680.  
  681.     # Shrink the frames after
  682.     #
  683.     set from $item
  684.     set to   [expr "$data(nItems)-1"]
  685.     tixPanedWindow:Iterate $w $from $to tixPanedWindow:Shrink $n
  686.  
  687.     # Graw the frame before
  688.     #
  689.     set from [expr $item-1]
  690.     set to   0
  691.     tixPanedWindow:Iterate $w $from $to tixPanedWindow:Grow $n
  692.  
  693.     set data(curSize) $p
  694. }
  695.  
  696. proc tixPanedWindow:CancleLines {w} {
  697.     upvar #0 $w data
  698.  
  699.     if [info exists data(lines)] {
  700.     foreach line $data(lines) {
  701.         set x1 [lindex $line 0]
  702.         set y1 [lindex $line 1]
  703.         set x2 [lindex $line 2]
  704.         set y2 [lindex $line 3]
  705.  
  706.         tixTmpLine $x1 $y1 $x2 $y2 $w
  707.     }
  708.  
  709.     catch {unset data(lines)}
  710.     }
  711. }
  712.  
  713. proc tixPanedWindow:PlotHandles {w transient} {
  714.     global tcl_platform
  715.  
  716.     upvar #0 $w data
  717.  
  718.     set totalsize 0
  719.     set i 0
  720.  
  721.     if {$data(-orientation) == "vertical"} {
  722.     set btnp [expr [winfo width $w]-13]
  723.     } else {
  724.     set h [winfo height $w]
  725.     if {$h > 18} {
  726.         set btnp 9
  727.     } else {
  728.         set btnp [expr $h-9]
  729.     }
  730.     }
  731.  
  732.     set firstpane [lindex $data(items) 0]
  733.     set totalsize $data($firstpane,size)
  734.  
  735.     if {$transient} {
  736.     tixPanedWindow:CancleLines $w
  737.     set data(lines) ""
  738.     }
  739.  
  740.     for {set i 1} {$i < $data(nItems)} {incr i} {
  741.     if {! $transient} {
  742.         if {$data(-orientation) == "vertical"} {
  743.         # CYGNUS LOCAL: Don't use buttons on Windows
  744.         if {$tcl_platform(platform) != "windows"} then {
  745.             place $data(btn,$i) -x $btnp -y [expr "$totalsize-4"]
  746.         }
  747.         place $data(sep,$i) -x 0 -y [expr "$totalsize-1"] -relwidth 1
  748.         } else {
  749.         # CYGNUS LOCAL: Don't use buttons on Windows
  750.         if {$tcl_platform(platform) != "windows"} then {
  751.             place $data(btn,$i) -y $btnp -x [expr "$totalsize-5"]
  752.         }
  753.         place $data(sep,$i) -y 0 -x [expr "$totalsize-1"] -relheight 1
  754.         }
  755.     } else {
  756.         if {$data(-orientation) == "vertical"} {
  757.         set x1 [winfo rootx $w]
  758.         set x2 [expr $x1 + [winfo width $w]]
  759.         set y  [expr $totalsize-1+[winfo rooty $w]]
  760.  
  761.         tixTmpLine $x1 $y $x2 $y $w
  762.         lappend data(lines) [list $x1 $y $x2 $y]
  763.         } else {
  764.         set y1 [winfo rooty $w]
  765.         set y2 [expr $y1 + [winfo height $w]]
  766.         set x  [expr $totalsize-1+[winfo rootx $w]]
  767.  
  768.         tixTmpLine $x $y1 $x $y2 $w
  769.         lappend data(lines) [list $x $y1 $x $y2]
  770.         }
  771.     }
  772.  
  773.     set name [lindex $data(items) $i]
  774.     incr totalsize $data($name,size)
  775.     }
  776. }
  777.  
  778. proc tixPanedWindow:BtnUp {w item {fake 0}} {
  779.     upvar #0 $w data
  780.  
  781.     if {!$fake} {
  782.     tixPanedWindow:CancleLines $w
  783.     }
  784.  
  785.     tixPanedWindow:UpdateSizes $w
  786.  
  787.     if {!$fake} {
  788.     $data(btn,$item) config -relief raised
  789.     grab release $data(btn,$item)
  790.     }
  791. }
  792.  
  793.  
  794. proc tixPanedWindow:HighlightBtn {w item} {
  795.     upvar #0 $w data
  796.  
  797.     $data(btn,$item) config -background $data(-handleactivebg)
  798. }
  799.  
  800. proc tixPanedWindow:DeHighlightBtn {w item} {
  801.     upvar #0 $w data
  802.  
  803.     $data(btn,$item) config -background $data(-handlebg)
  804. }
  805.  
  806. #----------------------------------------------------------------------
  807. #
  808. #
  809. # Geometry management routines
  810. #
  811. #
  812. #----------------------------------------------------------------------
  813.  
  814. # update the sizes of each pane according to the data($name,size) variables
  815. #
  816. proc tixPanedWindow:UpdateSizes {w} {
  817.     global tcl_platform
  818.  
  819.     upvar #0 $w data
  820.  
  821.     set data(totalsize) 0
  822.  
  823.     set mw [winfo width  $w]
  824.     set mh [winfo height $w]
  825.  
  826.     for {set i 0} {$i < $data(nItems)} {incr i} {
  827.     set name [lindex $data(items) $i]
  828.  
  829.     if {$data($name,size) > 0} {
  830.         if {$data(-orientation) == "vertical"} {
  831.         tixMoveResizeWindow $w.$name 0 $data(totalsize) \
  832.             $mw $data($name,size)
  833.         tixMapWindow $w.$name
  834.         raise $w.$name
  835.         } else {
  836.         tixMoveResizeWindow $w.$name $data(totalsize) 0 \
  837.             $data($name,size) $mh
  838.         tixMapWindow $w.$name
  839.         raise $w.$name
  840.         }
  841.     } else {
  842.         tixUnmapWindow $w.$name
  843.     }
  844.     incr data(totalsize) $data($name,size)
  845.     }
  846.  
  847.     # Reset the color and width of the separator
  848.     #
  849.     if {$data(-orientation) == "vertical"} {
  850.     set spec -height
  851.     } else {
  852.     set spec -width
  853.     }
  854.  
  855.     # CYGNUS LOCAL: On Windows, use a thicker line.
  856.     if {$tcl_platform(platform) == "windows"} then {
  857.     set thickness 4
  858.     } else {
  859.     set thickness 2
  860.     }
  861.  
  862.     for {set i 1} {$i < $data(nItems)} {incr i} {
  863.     $data(sep,$i) config -bg $data(-separatorbg) $spec $thickness
  864.     raise $data(sep,$i)
  865.     raise $data(btn,$i)
  866.     }
  867.  
  868.  
  869.     # Invoke the callback command
  870.     #
  871.     if {$data(-command) != ""} {
  872.     set sizes ""
  873.     foreach item $data(items) {
  874.         lappend sizes $data($item,size)
  875.     }
  876.     set bind(specs) ""
  877.     tixEvalCmdBinding $w $data(-command) bind [list $sizes]
  878.     }
  879. }
  880.  
  881. proc tixPanedWindow:GetNaturalSizes {w} {
  882.     upvar #0 $w data
  883.  
  884.     set data(totalsize) 0
  885.     set totalreq 0
  886.  
  887.     if {$data(-orientation) == "vertical"} {
  888.     set majorspec height
  889.     set minorspec width
  890.     } else {
  891.     set majorspec width
  892.     set minorspec height
  893.     }
  894.  
  895.     set minorsize 0
  896.     foreach name $data(items) {
  897.     if {[winfo manager $w.$name] != "tixGeometry"} {
  898.         error "Geometry management error: pane \"$w.$name\" cannot be managed by \"[winfo manager $w.$name]\"\nhint: delete the line \"[winfo manager $w.$name] $w.$name ...\" from your program"
  899.     }
  900.  
  901.     # set the minor size
  902.     #
  903.     set req_minor [winfo req$minorspec $w.$name]
  904.  
  905.     if {$req_minor > $minorsize} {
  906.         set minorsize $req_minor
  907.     }
  908.  
  909.     # Check the natural size against the max, min requirements.
  910.     # Change the natural size if necessary
  911.     #
  912.     if {$data($name,size) <= 1} {
  913.         set data($name,size) [winfo req$majorspec $w.$name]
  914.     }
  915.  
  916.     if {$data($name,size) > 1} {
  917.         # If we get zero maybe the widget was not initialized yet ...
  918.         #
  919.         # %% hazard : what if the window is really 1x1?
  920.         #
  921.         if {$data($name,size) < $data($name,min)} {
  922.         set data($name,size) $data($name,min)
  923.         }
  924.         if {$data($name,size) > $data($name,max)} {
  925.         set data($name,size) $data($name,max)
  926.         }
  927.     }
  928.  
  929.     # kludge: because a frame always returns req size of {1,1} before
  930.     # the packer processes it, we do the following to mark the
  931.     # pane as "size unknown"
  932.     #
  933. #    if {$data($name,size) == 1 && ![winfo ismapped $w.$name]} {
  934. #        set data($name,size) 0
  935. #    }
  936.  
  937.     # Add up the total size
  938.     #
  939.     incr data(totalsize) $data($name,size)
  940.  
  941.     # Find out the request size
  942.     #
  943.     if {$data($name,rsize) == 0} {
  944.         set rsize [winfo req$majorspec $w.$name]
  945.     } else {
  946.         set rsize $data($name,rsize)
  947.     }
  948.  
  949.     if {$rsize < $data($name,min)} {
  950.         set rsize $data($name,min)
  951.     }
  952.     if {$rsize > $data($name,max)} {
  953.         set rsize $data($name,max)
  954.     }
  955.  
  956.     incr totalreq $rsize
  957.     }
  958.  
  959.     if {$data(-orientation) == "vertical"} {
  960.     return "$minorsize $totalreq"
  961.     } else {
  962.     return "$totalreq $minorsize"
  963.     }
  964. }
  965.  
  966. #--------------------------------------------------
  967. # Handling resize
  968. #--------------------------------------------------
  969. proc tixPanedWindow:ClientGeomProc {w type client} {
  970.     tixPanedWindow:RepackWhenIdle $w
  971. }
  972.  
  973. #
  974. # This monitor the sizes of the master window
  975. #
  976. proc tixPanedWindow:MasterGeomProc {w master} {
  977.     tixPanedWindow:RepackWhenIdle $w
  978. }
  979.  
  980. proc tixPanedWindow:RepackWhenIdle {w} {
  981.     if {![winfo exist $w]} {
  982.     return
  983.     }
  984.     upvar #0 $w data
  985.  
  986.     if {$data(repack) == 0} {
  987.     tixWidgetDoWhenIdle tixPanedWindow:Repack $w
  988.     set data(repack) 1
  989.     }
  990. }
  991.  
  992. #
  993. # This monitor the sizes of the master window
  994. #
  995. proc tixPanedWindow:Repack {w} {
  996.     upvar #0 $w data
  997.  
  998.     # Calculate the desired size of the master
  999.     #
  1000.     set dim [tixPanedWindow:GetNaturalSizes $w]
  1001.  
  1002.     if {$data(-width) != 0} {
  1003.     set mreqw $data(-width)
  1004.     } else {
  1005.     set mreqw [lindex $dim 0]
  1006.     }
  1007.  
  1008.     if {$data(-height) != 0} {
  1009.     set mreqh $data(-height)
  1010.     } else {
  1011.     set mreqh [lindex $dim 1]
  1012.     }
  1013.  
  1014.     if !$data(-dynamicgeometry) {
  1015.     if {$mreqw < $data(maxReqW)} {
  1016.         set mreqw $data(maxReqW)
  1017.     }
  1018.     if {$mreqh < $data(maxReqH)} {
  1019.         set mreqh $data(maxReqH)
  1020.     }
  1021.     set data(maxReqW) $mreqw
  1022.     set data(maxReqH) $mreqh
  1023.     }
  1024.     if {$mreqw != [winfo reqwidth $w] || $mreqh != [winfo reqheight $w] } {
  1025.     if {![info exists data(counter)]} {
  1026.         set data(counter) 0
  1027.     }
  1028.     if {$data(counter) < 50} {
  1029.         incr data(counter)
  1030.         tixGeometryRequest $w $mreqw $mreqh
  1031.         tixWidgetDoWhenIdle tixPanedWindow:Repack $w
  1032.         set data(repack) 1
  1033.         return
  1034.     }
  1035.     }
  1036.  
  1037.     set data(counter) 0
  1038.  
  1039.     if {$data(nItems) == 0} {
  1040.     set data(repack) 0
  1041.     return
  1042.     }
  1043.  
  1044.     tixWidgetDoWhenIdle tixPanedWindow:DoRepack $w
  1045. }
  1046.  
  1047. proc tixPanedWindow:DoRepack {w} {
  1048.     upvar #0 $w data
  1049.  
  1050.     if {$data(-orientation) == "vertical"} {
  1051.     set newSize [winfo height $w]
  1052.     } else {
  1053.     set newSize [winfo width $w]
  1054.     }
  1055.  
  1056.     if {$newSize <= 1} {
  1057.     # Probably this window is too small to see anyway
  1058.     # %%Kludge: I don't know if this always work.
  1059.     #
  1060.     set data(repack) 0
  1061.     return
  1062.     }
  1063.  
  1064.     set totalExp 0
  1065.     foreach name $data(items) {
  1066.     set totalExp [expr $totalExp + $data($name,expand)]
  1067.     }
  1068.  
  1069.     if {$newSize > $data(totalsize)} {
  1070.     # Grow
  1071.     #
  1072.     set toGrow [expr "$newSize-$data(totalsize)"]
  1073.  
  1074.     set p [llength $data(items)]
  1075.     foreach name $data(items) {
  1076.         set toGrow [tixPanedWindow:xGrow $w $name $toGrow $totalExp $p]
  1077.         if {$toGrow > 0} {
  1078.         set totalExp [expr $totalExp-$data($name,expand)]
  1079.         incr p -1
  1080.         } else {
  1081.         break
  1082.         }
  1083.     }
  1084.     } else {
  1085.     # Shrink
  1086.     #
  1087.     set toShrink [expr "$data(totalsize)-$newSize"]
  1088.  
  1089.     set usedSize 0
  1090.     foreach name $data(items) {
  1091.         set toShrink [tixPanedWindow:xShrink $w $name $toShrink \
  1092.         $totalExp $newSize $usedSize]
  1093.         if {$toShrink > 0} {
  1094.         set totalExp [expr $totalExp-$data($name,expand)]
  1095.         incr usedSize $data($name,size)
  1096.         } else {
  1097.         break
  1098.         }
  1099.     }
  1100.     }
  1101.  
  1102.     tixPanedWindow:UpdateSizes $w
  1103.     tixPanedWindow:PlotHandles $w 0
  1104.  
  1105.     set data(repack) 0
  1106. }
  1107.  
  1108. #--------------------------------------------------
  1109. # Shrink and grow items
  1110. #--------------------------------------------------
  1111. #   toGrow: how much free area to grow into
  1112. #        p: == 1 if $name is the last in the list of items
  1113. # totalExp: used to calculate the amount of the free area that this
  1114. #        window can grow into
  1115. #
  1116. proc tixPanedWindow:xGrow {w name toGrow totalExp p} {
  1117.     upvar #0 $w data
  1118.  
  1119.     if {$p == 1} {
  1120.     set canGrow $toGrow
  1121.     } else {
  1122.     if {$totalExp == 0} {
  1123.         set canGrow 0
  1124.     } else {
  1125.         set canGrow [expr int($toGrow * $data($name,expand) / $totalExp)]
  1126.     }
  1127.     }
  1128.  
  1129.     if {[expr $canGrow + $data($name,size)] > $data($name,max)} {
  1130.     set canGrow [expr $data($name,max) - $data($name,size)]
  1131.     }
  1132.  
  1133.     incr data($name,size) $canGrow
  1134.     incr toGrow -$canGrow
  1135.  
  1136.     return $toGrow
  1137. }
  1138.  
  1139. proc tixPanedWindow:xShrink {w name toShrink totalExp newSize usedSize} {
  1140.     upvar #0 $w data
  1141.  
  1142.     if {$totalExp == 0} {
  1143.     set canShrink 0
  1144.     } else {
  1145.     set canShrink [expr int($toShrink * $data($name,expand) / $totalExp)]
  1146.     }
  1147.  
  1148.     if {[expr $data($name,size) - $canShrink] < $data($name,min)} {
  1149.     set canShrink [expr $data($name,size) -$data($name,min)]
  1150.     }
  1151.     if {[expr $usedSize + $data($name,size) - $canShrink] > $newSize} {
  1152.     set data($name,size) [expr $newSize - $usedSize]
  1153.     return 0
  1154.     } else {
  1155.     incr data($name,size) -$canShrink
  1156.     incr toShrink -$canShrink
  1157.  
  1158.     return $toShrink
  1159.     }
  1160. }
  1161.  
  1162. #--------------------------------------------------
  1163. # Shrink and grow items
  1164. #--------------------------------------------------
  1165. proc tixPanedWindow:Shrink {w name n} {
  1166.     upvar #0 $w data
  1167.  
  1168.     set canShrink [expr "$data($name,size) - $data($name,min)"]
  1169.  
  1170.     if {$canShrink > $n} {
  1171.     incr data($name,size) -$n
  1172.     return 0
  1173.     } elseif {$canShrink > 0} {
  1174.     set data($name,size) $data($name,min)
  1175.     incr n -$canShrink
  1176.     }
  1177.     return $n
  1178. }
  1179.  
  1180. proc tixPanedWindow:Grow {w name n} {
  1181.     upvar #0 $w data
  1182.  
  1183.     set canGrow [expr "$data($name,max) - $data($name,size)"]
  1184.  
  1185.     if {$canGrow > $n} {
  1186.     incr data($name,size) $n
  1187.     return 0
  1188.     } elseif {$canGrow > 0} {
  1189.     set data($name,size) $data($name,max)
  1190.     incr n -$canGrow
  1191.     }
  1192.  
  1193.     return $n
  1194. }
  1195.  
  1196. proc tixPanedWindow:Iterate {w from to proc n} {
  1197.     upvar #0 $w data
  1198.  
  1199.     if {$from <= $to} {
  1200.     for {set i $from} {$i <= $to} {incr i} {
  1201.         set n [$proc $w [lindex $data(items) $i] $n]
  1202.         if {$n == 0} {
  1203.         break
  1204.         }
  1205.     }
  1206.     } else {
  1207.     for {set i $from} {$i >= $to} {incr i -1} {
  1208.         set n [$proc $w [lindex $data(items) $i] $n]
  1209.         if {$n == 0} {
  1210.         break
  1211.         }
  1212.     }
  1213.     }
  1214. }
  1215.